﻿// 1002 修路.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <unordered_set>

using  namespace std;
/*
http://oj.daimayuan.top/course/7/problem/546


有 n个城市，城市的编号为 1到 n。
城市之间已经修好了 m条道路，第 i条道路连接了第 xi和第 yi个城市。

请问最少再修几条道路，可以使得所有城市都连通（也就是说，我们可以通过道路从任意一个城市到另一个城市）？

输入格式
第一行两个整数 n,m，代表城市数量和已修道路数。

接下来 m行，每行两个整数 x,y，表示一条连接第 x个和第 y个城市的道路。

输出格式
输出一行一个数表示答案。

样例输入
5 4
1 2
2 3
1 3
4 5
样例输出
1
数据规模
对于所有数据，保证 1≤n,m≤100000,1≤x,y≤n,x≠y。
*/


const int N = 100010;
int f[N];


void init() {
    for (int i = 0; i < N; i++) f[i] = i;
}

int find(int x) {
    if (f[x] != x) f[x] = find(f[x]);
    return f[x];
}

void merge(int a, int b ) {
    f[find(a)] = find(b);
}

int n, m;
int main()
{
    cin >> n >> m;
    init();
    for (int i = 0; i < m; i++) {
        int a, b; cin >> a >> b;
        merge(a, b);
    }

    unordered_set<int> ss;
    for (int i = 1; i <= n; i++) {
        ss.insert(find(i));
    }

    cout << ss.size() - 1 << endl;

    return 0;
}

 